/**
 * @file LspAccess_interface.h
 * @author Фетисов Михаил Вячеславович (fetisov.michael@yandex.ru)
 * @brief Объявление интерфейса доступа к функциям LSP из плагинов.
 * @version 0.1
 * @date 2023-04-04
 *
 * @copyright MIT: Michael Fetisov, Anton Bushev
 *
 */
#ifndef simodo_shell_LspAccess_interface_H
#define simodo_shell_LspAccess_interface_H

#include "simodo/shell/access/LspStructures.h"
#include "simodo/lsp-client/CompletionParams.h"
#include "simodo/lsp-client/ServerCapabilities.h"
#include "simodo/lsp-client/SimodoCapabilities.h"

namespace simodo::shell
{
    /**
     * @brief Возможности сервера.
     * 
     * @note Перечислены только поддерживаемые оболочкой возможности.
     * 
     */
    enum class ServerCapability
    {
        /// @brief Подсказка при наведении мышкой на символ (терминальный элемент грамматики)
        hover,
        /// @brief Перечень (часто иерархической структуры) символов для отображения в навигационной панели 
        /// (обычно располагается над редактором)
        documentSymbol,
        /// @brief Перечень всех (или тех, которые поддерживаются) символов с их семантической информации
        /// (для более выразительного выделения)
        semanticTokens,
        /// @brief Переход на объявление символа (обычно F12 или Ctrl-LeftMouseClick)
        declaration,
        /// @brief Переход на объявление символа (обычно F12 или Ctrl-LeftMouseClick)
        definition,
        /// @brief Подсказка возможного продолжения ввода для текущего положения текстового курсора
        completion
    };

    /**
     * @brief Интерфейс доступа к функциям LSP (см. https://en.wikipedia.org/wiki/Language_Server_Protocol),
     * предоставляемый оболочкой.
     * 
     * @details
     * Может быть получен с помощью метода Access_interface::getLspAccess.
     *
     */
    class LspAccess_interface
    {
    public:
        virtual ~LspAccess_interface() = default;

        /**
         * @brief Получение мнемокода (идентификатора) языка для заданного пути (uri) документа
         * 
         * @param path путь к файлу документа
         * @return QString
        */
        virtual QString getLanguageId(const QString & path) = 0;

        /**
         * @brief Проверка поддерживается ли заданная возможность LSP для заданного файла.
         * 
         * @param path путь к файлу
         * @param capability возможность
         * @return true - поддерживается
         * @return false - не поддерживается
         */
        virtual bool checkServerCapability(const QString & path, ServerCapability capability) = 0;

        /**
         * @brief Получение развёрнутой структуры поддержки возможностей LSP-сервера для заданного файла
         * 
         * @param path путь к файлу
         * @return const lsp::ServerCapabilities& 
         */
        virtual lsp::ServerCapabilities getServerCapabilities(const QString & path) = 0;

        /**
         * @brief Получение развёрнутой структуры поддержки возможностей SIMODO в LSP-сервера для заданного файла
         * 
         * @param path путь к файлу
         * @return const lsp::SimodoCapabilities & 
         */
        virtual lsp::SimodoCapabilities getSimodoCapabilities(const QString & path) = 0;

        /**
         * @brief Передача на LSP-сервер нотификации об изменении файла.
         * 
         * @details 
         * В соответствии со спецификацией LSP, после получения данной нотификации сервер должен
         * выслать нотификацию о диагностике (см. метод ViewAdaptorLsp_interface::publishDiagnostics).
         * После этого можно выполнить запросы на получение дополнительной информации (см. методы:
         * documentSymbol, semanticTokens).
         * 
         * @note Пока поддерживается только передача полного содержимого при изменении
         * 
         * @param path путь к файлу
         * @param version версия изменений
         */
        virtual void didChange(const QString & path, int version) = 0;

        /**
         * @brief Запрос информации на получение подсказки по заданной позиции в документе.
         * 
         * При получении данного запроса, сервер высылает ответ, который оболочка передаёт адаптеру представления
         * документа (см. метод ViewAdaptorLsp_interface::hover).
         * 
         * @param sender Указатель на отправителя (необходим, если выполняется работа сразу с несколькими однотипными виджетами)
         * @param path путь к файлу
         * @param line номер строки (с нуля)
         * @param character номер позиции в строке (с нуля)
         */
        virtual void hover(const void * sender, const QString & path, int line, int character) = 0;

        /**
         * @brief Запрос на получение символов для навигации по документу, заданному путём к его файлу.
         * 
         * При получении данного запроса, сервер высылает ответ, который оболочка передаёт адаптеру представления
         * документа (см. метод ViewAdaptorLsp_interface::documentSymbol).
         * 
         * @param path путь к файлу документа
         */
        virtual void documentSymbol(const QString & path) = 0;

        /**
         * @brief Запрос на получение символов с подробной семантической информацией для более выразительной подсветки.
         * 
         * При получении данного запроса, сервер высылает ответ, который оболочка передаёт адаптеру представления
         * документа (см. метод ViewAdaptorLsp_interface::semanticTokens).
         * 
         * @param path путь к файлу документа
         */
        virtual void semanticTokens(const QString & path) = 0;

        /**
         * @brief Запрос на получение координат объявления символа по заданной позиции.
         * 
         * При получении данного запроса, сервер высылает ответ, который оболочка обрабатывает самостоятельно.
         * 
         * @param path путь к файлу документа
         * @param line номер строки (с нуля)
         * @param character номер позиции в строке (с нуля)
         */
        virtual void declaration(const QString & path, int line, int character) = 0;

        /**
         * @brief Запрос на получение координат определения символа по заданной позиции.
         * 
         * При получении данного запроса, сервер высылает ответ, который оболочка обрабатывает самостоятельно.
         * 
         * @param path путь к файлу документа
         * @param line номер строки (с нуля)
         * @param character номер позиции в строке (с нуля)
         */
        virtual void definition(const QString & path, int line, int character) = 0;

        /**
         * @brief Запрос на получение информации о возможных продолжениях ввода
         * 
         * При получении данного запроса, сервер высылает ответ, который оболочка передаёт адаптеру представления
         * документа (см. метод ViewAdaptorLsp_interface::completionItems).
         * 
         * @param sender Указатель на отправителя (необходим, если выполняется работа сразу с несколькими однотипными виджетами)
         * @param path путь к файлу документа
         * @param line номер строки (с нуля)
         * @param character номер позиции в строке (с нуля)
         * @param trigger_kind причина инициирования запроса
         * @param trigger_character символ, ввод которого привёл к запросу
         */
        virtual void completion(const void * sender, const QString & path, int line, int character, 
                                lsp::CompletionTriggerKind trigger_kind, 
                                const QString & trigger_character) = 0;

        /**
         * @brief Запрос на запуск на выполнение команды по дополнению протокола LSP
         * @param path путь к файлу документа
         * @param command Мнемокод команды
        */
        virtual void executeSimodoCommand(const QString & path, const QString & command /*Тут должны быть параметры команды*/) = 0;
    };

}

#endif // simodo_shell_LspAccess_interface_H